<template>
  <div class="ek-table">
    <!-- 按钮操作区域 -->
    <div class="table-operate">
      <el-row>
        <el-button
          class="icon-btn"
          type="primary"
          @click.stop="handleRefresh"
          :loading="refreshing ? true : false"
          :size="size"
        >
          <el-icon class="icon iconfont icon-refresh" size="22" />
        </el-button>
        <el-col :span="16" v-if="config.operateOn">
          <div class="operate-right">
            <slot name="operate">
              <template v-if="ekButtons?.length">
                <el-button
                  :size="size"
                  v-for="(item, index) in ekButtons"
                  :key="index"
                  @click.stop="handleOperate(item)"
                  :loading="item.loading ? true : false"
                >
                  <el-icon :class="item.icon" size="22" />
                  {{ item.text }}
                </el-button>
              </template>
            </slot>
          </div>
        </el-col>
        <el-col :span="8"> </el-col>
      </el-row>
    </div>

    <el-table
      :data="tableData"
      border
      empty-text="空空如也"
      :show-summary="showSummary"

      :height="height"
      :max-height="maxHeight"
      :row-key="rowKey"
      :default-expand-all="defaultExpandAll"
      @sort-change="handleSortChange"
      @selection-change="handleSelectionChange"
      @current-change="handleCurrentChange"
      highlight-current-row
      ref="ekTable"
      :size="size"
      @cell-click="handleCellClick"
      :expand-row-keys="expandRowKeys"
      :show-overflow-tooltip="true"
      v-loading="loading"
    >
      <template v-for="item in ekColumns" v-if="ekColumns?.length">
        <!-- 选择框 -->
        <el-table-column
          type="selection"
          :key="item.column"
          v-if="item.type == 'selection'"
          :reserve-selection="reserveSelection"
        >
        </el-table-column>
        <!-- 单选选择框-->
        <el-table-column
          :key="item.column"
          width="100"
          v-else-if="item.type == 'radio'"
        >
          <template #default="scope">
            <div style="display: inline">
              <el-radio
                :value="scope.row[rowKey]"
                v-model="currentRow[rowKey]"
              ></el-radio>
            </div>
          </template>
        </el-table-column>
        <!-- 字段显示区域 -->
        <el-table-column
          :type="item.type"
          :label="item.label"
          :width="item.width"
          :fixed="item.fixed"
          :sortable="item.sortable"
          :prop="item.column"
          :key="item.column"
          :show-overflow-tooltip="item.column == 'operate' ? false : true"
          v-else
        >
          <template #default="scope">
            <div v-if="item.column == 'operate'">
              <slot name="operateColumn" :scope="scope">
                <template v-if="item.buttons?.length">
                  <span
                    v-for="(button, index) in item.buttons"
                    :key="index"
                    class="table-operate-btn"
                    @click.stop="handleOperate(button, scope)"
                  >
                    {{ button.text }}
                  </span>
                </template>
              </slot>
            </div>
            <div style="display: inline" v-else>
              <slot :name="item.slot" :scope="scope" :item="item">
                <span
                  v-if="item.display == 'detail'"
                  class="table-detail"
                  @click.stop="openOther(item, scope)"
                >
                  {{ formatText(scope.row, item) }}
                </span>
                <span v-else-if="item.display == 'state'" class="table-state">
                  <el-tag
                    effect="light"
                    :type="['danger', 'success'][scope.row[item.column]]"
                  >
                    {{ formatText(scope.row, item) }}
                  </el-tag>
                </span>
                <!-- text -->
                <span v-else>
                  {{ formatText(scope.row, item) }}
                </span>
              </slot>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>

    <!-- 表单区域 -->
    <ekForm
      v-model:visiable="froms.visiable"
      :config="froms.config"
      :rowId="froms.rowId"
      :title="froms.config.title"
      :disabled="froms.disabled"
      :hideBtn="froms.hideBtn"
      :formJson="froms.formJson"
      @submit="handleSubmit"
      v-if="!froms.component && froms.visiable"
    >
    </ekForm>

    <!-- 自定义组件区域 -->
    <component
      v-model:visiable="froms.visiable"
      :is="froms.component"
      :rowId="froms.rowId"
      :title="froms.config.title"
      :disabled="froms.disabled"
      :hideBtn="froms.hideBtn"
      :selectionRows="selectionRows"
      @submit="handleSubmit"
      v-if="froms.component"
    >
    </component>
  </div>
</template>

<script setup>
import {
  defineComponent,
  onMounted,
  getCurrentInstance,
  ref,
  reactive,
  computed,
  watch,
  defineAsyncComponent,
  markRaw,
  nextTick,
} from "vue";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import ekForm from "@/components/business/ekForm";
import { exportExcel } from "@/utils/common";
import moment from "moment";

const props = defineProps({
  // 字段列表
  columns: {
    type: Array,
    default: () => {
      return [];
    },
  },
  showSummary: {
    type: Boolean,
    default: false,
  },

  // 表格数据
  tableData: {
    type: Array,
    default: () => {
      return [];
    },
  },
  // 地址配置
  configs: {
    type: Object,
    default: () => {
      return {};
    },
  },
  // 表格高度
  height: {
    type: [String, Number],
    default: null,
  },
  // 表格高度
  maxHeight: {
    type: [String, Number],
    default: null,
  },
  // 操作按钮
  buttons: {
    type: Array,
    default: () => {
      return [];
    },
  },
  // 表格加载中
  loading: {
    type: Boolean,
    default: false,
  },

  size: {
    type: String,
    default: "default",
  },
  // 行主键，用于单选
  rowKey: {
    type: String,
    default: "id",
  },
  // 保持选中行
  reserveSelection: {
    type: Boolean,
    default: false,
  },
  // 展开所有行
  defaultExpandAll: {
    type: Boolean,
    default: false,
  },
  expandRowKeys: {
    type: Array,
    default: () => {
      return [];
    },
  }
});

const {
  appContext: {
    config: { globalProperties },
  },
  proxy: { $nextTick },
} = getCurrentInstance();

const { $storage, $http, $ekMessage, $ekMessageBox } = globalProperties;
const store = useStore();
const router = useRouter();
const emit = defineEmits(["sort-change", "refresh", "opreate", "cell-click"]);

// 传入的配置
let config = computed(() => {
  return props.configs;
});
// 对象
let ekTable = ref(null);

// 接收按钮配置
const ekButtons = computed(() => {
  return props.buttons;
});

// 接收字段配置
const ekColumns = computed(() => {
  return props.columns;
});

// 行上字段事件，只支持详情
function openOther(item, scope) {
  // 自定义详情组件
  if (item.config?.mode == "custom") {
    customDetail(item, scope);
  } else {
    let button = {
      type: item.display,
      config: item.config,
    };
    this.handleOperate(button, scope);
  }
}
/* 表单区域 */
let typeName = {
  add: "新增",
  edit: "编辑",
  detail: "详情",
};
let froms = reactive({
  visiable: false, // 表单是否显示
  rowId: "", // 行id
  row: "", // 行数据
  type: "", // 表单类型
  disabled: false, // 是否禁用
  hideBtn: false, // 隐藏操作按钮
  formJson: {}, // 本地json
  component: "", // 组件地址，记住import引入的组件地址很重要
  config: {
    // 表单配置
  },
});

// 当前操作按钮
const currentButton = ref(null);
/**
 * 按钮操作
 * @param {*} button 按钮对象
 * @param {*} scope 当前行数据
 */
function handleOperate(button, scope) {
  currentButton.value = button;
  // 当前操作按钮
  let type = button.operate;
  // 操作类型
  froms.type = button.operate;
  // 行数据赋值
  froms.row = (scope && scope.row) || "";
  // 配置
  froms.config = {
    // 组件
    component: "",
    // 回调
    callback: "",
    // 标题
    title: typeName[froms.type] || "",
    // 操作完毕自动刷新
    autoReload: ["add", "edit", "delete"].includes(type) ? true : false,
    // 操作后自动关闭
    autoClose: ["add"].includes(type) ? true : false,
    ...button.config,
  };
  // 获取本地表单配置
  froms.formJson = button.config?.formJson || {};

  switch (type) {
    case "add":
      operateAdd(button, scope);
      break;
    case "edit":
      operateEdit(button, scope);
      break;
    case "detail":
      operateDetail(button, scope);
      break;
    case "delete":
      operateDelete(button, scope);
      break;
    case "export":
      operateExport(button, scope);
      break;
    case "customComponents":
      operateCustomComponents(button, scope);
      break;
    case "customJs":
      operateCustomJs(button, scope);
      break;
    default:
      break;
  }
}

// 新增
function operateAdd(button, scope) {
  froms.visiable = true;
  froms.disabled = false;
  froms.rowId = "";
  froms.hideBtn = false;
}
// 编辑
function operateEdit(button, scope) {
  froms.visiable = true;
  froms.disabled = false;
  froms.rowId = scope.row[button.config.id || "id"];
  froms.hideBtn = false;
}
// 详情
function operateDetail(button, scope) {
  froms.visiable = true;
  froms.disabled = true;
  froms.rowId = scope.row[button.config.id || "id"];
  froms.hideBtn = true;
}
// 删除
function operateDelete(button, scope) {
  let ids = "";
  if (scope) {
    // 行删除
    ids = [scope.row.id];
  } else {
    // 批量删除
    let selectRows = ekTable.value.getSelectionRows();
    ids = selectRows.map((item) => item.id);
  }
  if (!ids.length) {
    $ekMessage.warning("请选择要删除的数据");
    return;
  }
  let deleteUrl =
    button.config.deleteUrl ||
    `/business/basis/delete?modelCode=${button.config.modelCode}`;
  $ekMessageBox
    .confirm("确认删除？")
    .then(() => {
      button.loading = true;
      $http
        .post(deleteUrl, {
          ids: ids,
        })
        .then((res) => {
          button.loading = false;
          operateCallback();
          $ekMessage.success("操作成功！");
        });
    })
    .catch(() => {
      button.loading = false;
    });
}
// 导出
function operateExport(button, scope) {
  button.loading = true;
  $http
    .post(
      button.config.exportUrl ||
        `/business/basis/export?modelCode=${button.config.modelCode}`,
      { responseType: "arraybuffer" }
    )
    .then((res) => {
      button.loading = false;
      exportExcel(res, "测试");
      $ekMessage.success("操作成功！");
      operateCallback();
    })
    .catch(() => {
      button.loading = false;
    });
}
// 自定义组件
async function operateCustomComponents(button, scope) {
  // 此处组件引入必须有明确目录位置，不然会找不到组件
  froms.component = markRaw(
    defineAsyncComponent(() =>
      import(`/src/views/${button.config.component}.vue`)
    )
  );

  froms.visiable = true;
  froms.disabled = button.config.disabled || false;
  froms.hideBtn = button.config.hideBtn || false;
  froms.rowId = (scope && scope.row && scope.row.id) || "";
}
// 自定义组件
async function customDetail(button, scope) {
  // 此处组件引入必须有明确目录位置，不然会找不到组件
  froms.component = markRaw(
    defineAsyncComponent(() =>
      import(`/src/views/${button.config.component}.vue`)
    )
  );
  // 配置
  froms.config.title = "详情";
  froms.disabled = true;
  froms.rowId = (scope && scope.row && scope.row[button.column]) || "";
  setTimeout(() => {
    // 这里处理主要是未了让组件先渲染
    froms.visiable = true;
  }, 50);
}

// 自定义js
function operateCustomJs(button, scope) {
  operateCallback();
}
// 刷新
const refreshing = ref(false);
function handleRefresh() {
  refreshing.value = true;
  emit("refresh", () => {
    refreshing.value = false;
  });
}
// 提交回调
function handleSubmit(done) {
  operateCallback(done);
}
// 操作回调统一入口，新增，保存等确认类操作需要执行done进行窗口关闭
function operateCallback(done) {
  // 如果配置了回调函数，必须执行 结束方法
  if (froms.config.callback) {
    if (typeof froms.config.callback === "function") {
      froms.config.callback({
        row: froms.row,
        rows: getSelectionRows(),
        button: currentButton.value,
        done: () => {
          // 需要进行列表刷新操作
          if (froms.config.autoReload) {
            emit("operateCallback");
          }
          // 回调关闭弹窗
          if (froms.config.autoClose) {
            done && done();
          }
        },
      });
    } else {
      const fn = new Function("{ row, rows, done}", froms.config.callback);
      // 回传操作行id 和选中数据
      fn.call(this, {
        row: froms.row,
        rows: getSelectionRows(),
        button: currentButton.value,
        done: () => {
          // 需要进行列表刷新操作
          if (froms.config.autoReload) {
            emit("operateCallback");
          }
          // 回调关闭弹窗
          if (froms.config.autoClose) {
            done && done();
          }
        },
      });
    }
  } else {
    // 需要进行列表刷新操作
    if (froms.config.autoReload) {
      emit("operateCallback");
    }
    // 回调关闭弹窗
    if (froms.config.autoClose) {
      done && done();
    }
  }
}
/* 表单区域结束  */
// 状态逻辑处理
// function formatterState(config, row) {
//   let options = config.options || [];
//   let column =   config.column || '';
//   if(options?.length && column){
//      let datas = options.find(el => el.value == row[column])
//      return datas.label;
//   } else {
//     return '#09be4f'
//   }

// }
// function formatterState(fnstr, row){
//   if(fnstr){
//       if(typeof fnstr === 'function'){
//         return fnstr({ row: row})
//       }else {
//         const fn = new Function('{ row }', fnstr);
//         return fn.call(this, { row: row });
//       }
//   } else {
//     return '#67c23a';
//   }
// }
// 排序
function handleSortChange({ column, prop, order }) {
  emit("sort-change", { column, prop, order });
}
// 选中的数据
let selection = ref([]); // 选中行
let currentRow = ref(""); // 当前选中行
function handleSelectionChange(data) {
  console.log(selectionRows.value);
  selection.value = selectionRows.value;
}
function handleCurrentChange(data) {
  if (data && Object.keys(data)) {
    currentRow.value = data;
  }
}

function handleCellClick(row, column, cell, event) {
  emit("cell-click", row, column, cell, event);
}
function formatText(row, item) {
  let format = item.format || "";
  let value = row[item.column];
  switch (format) {
    case "date":
      if (value) {
        return moment(Number(value) * 1000).format("YYYY-MM-DD");
      }
      return "-";
    case "datetime":
      if (value) {
        return moment(Number(value) * 1000).format("YYYY-MM-DD HH:mm:ss");
      }
      return "-";
    case "dim":
      if (value || value == 0) {
        return row[item.column + "_dim_text"];
      }
      return "-";
    case "model":
      if (value) {
        return row[item.column + "_model_text"];
      }
      return "-";
    default:
      if (value || value == 0) {
        return value;
      }
      return "-";
  }
}
const selectionRows = computed({
  get() {
    return ekTable.value ? ekTable.value.getSelectionRows() : [];
  },
});
// 获取所有选中的行
function getSelectionRows() {
  return ekTable.value.getSelectionRows();
}
// 获取当前选中的行
function getCurrentRow() {
  return currentRow.value;
}
// 暴露给外部的方法
defineExpose({
  getSelectionRows,
  getCurrentRow,
});
</script>

<style scoped lang="scss">
.ek-table {
  .table-operate {
    padding: 8px 0;
    .icon-btn {
      padding: 0 8px;
    }
    .operate-left {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      height: 100%;
      > span {
        padding: 0 4px;
        color: var(--text-color);
      }
    }
    .operate-right {
      height: 100%;
      display: flex;
      justify-content: flex-start;
      align-items: center;
      height: 100%;
    }
  }
  .table-detail {
    color: var(--text-link-color);
  
    cursor: pointer;
  }
  .table-operate-btn {
    padding: 0 4px;
    cursor: pointer;
    color: var(--text-link-color);
    font-size: 13px;
    margin-left: 0;
    border: none;
    &:hover {
      color: var(--text-link-hover-color);
    }
  }
}
</style>
